package pers.lee.util.demo;

import java.util.AbstractMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;

/**
 * @author lixiaoying 2018年2月3日 上午9:18:10
 * @param <K>
 */
public class SimpleMap<K, V> extends AbstractMap<K, V> {

	/**
	 * bucket容量 使用2的整数次方的长度，可以在get时使用掩码的方式，而非较慢的除法与求余
	 */
	static final int SIZE = 1024;

	private LinkedList<SimpleEntry<K, V>>[] buckets = new LinkedList[SIZE];

	@Override
	public V get(Object key) {
		int index = Math.abs(key.hashCode()) % SIZE;
		if (buckets[index] == null) {
			return null;
		}
		for (SimpleEntry<K, V> entry : buckets[index]) {
			if (entry.getKey().equals(key)) {
				return entry.getValue();
			}
		}
		return null;
	}

	@Override
	public V put(K key, V value) {
		V oldValue = null;
		int index = Math.abs(key.hashCode()) % SIZE;
		if (buckets[index] == null) {
			buckets[index] = new LinkedList();
		}
		boolean found = false;
		LinkedList<SimpleEntry<K, V>> bucket = buckets[index];
		SimpleEntry<K, V> pair = new SimpleEntry(key, value);
		ListIterator<SimpleEntry<K, V>> it = bucket.listIterator();
		while (it.hasNext()) {
			SimpleEntry<K, V> iPair = it.next();
			if (iPair.getKey().equals(key)) {
				oldValue = iPair.getValue();
				iPair.setValue(value);
				found = true;
				break;
			}
		}
		if (!found) {
			bucket.add(pair);
		}
		return oldValue;
	}

	@Override
	public Set<Map.Entry<K, V>> entrySet() {
		Set<Map.Entry<K, V>> set = new HashSet();
		for (LinkedList<SimpleEntry<K, V>> bucket : buckets) {
			if (bucket == null) {
				continue;
			}
			for (SimpleEntry<K, V> entry : bucket) {
				set.add(entry);
			}
		}
		return set;
	}

	public static void main(String[] args) {
		SimpleMap simpleMap = new SimpleMap();
		simpleMap.put("China", "东亚");
		simpleMap.put("America", "美洲");
		simpleMap.put("Japan", "东亚");
		System.out.println(simpleMap);
		System.out.println(simpleMap.entrySet());

	}
}
